home *** CD-ROM | disk | FTP | other *** search
- /*
- ### quality controlled Runge-Kutta integrator one-stepper ###
-
- Note: a slightly modified version of rkqc in "Numerical Recipes"
- c convention of [0,n-1] is used
- */
-
- #include <stdio.h>
- #include <math.h>
- #define PGROW -0.20
- #define PSHRINK -0.25
- #define FCOR 6.666666666666667e-2
- #define SAFETY 0.9
- #define ERRCON 6.0e-4
-
- void rkqc(y,dydx,n,x,htry,eps,yscal,hdid,hnext)
- double y[],dydx[],*x,htry,eps,yscal[],*hdid,*hnext;
- int n;
- {
- int i;
- double xsav,hh,h,temp,errmax;
- double *dysav,*ysav,*ytemp,*dvector();
- void free_dvector();
- extern int model;
- extern double *param;
- extern int (*f_p)();
-
- dysav = dvector(0,n-1);
- ysav = dvector(0,n-1);
- ytemp = dvector(0,n-1);
- xsav = (*x);
- for(i=0;i<n;i++){
- ysav[i] = y[i];
- dysav[i] = dydx[i];
- }
- h = htry;
- for(;;){
- hh = 0.5 * h;
- (void) rk4(ysav,dysav,n,xsav,hh,ytemp);
- *x = xsav + hh;
- (int) f_p(dydx,0,ytemp,param,*x,n);
- (void) rk4(ytemp,dydx,n,*x,hh,y);
- *x = xsav + h;
- if(*x == xsav) system_mess_proc(1,"rkqc: Step size too small. Stop");
- (void) rk4(ysav,dysav,n,xsav,h,ytemp);
- errmax = 0.0;
- for(i=0;i<n;i++){
- ytemp[i] = y[i] - ytemp[i];
- temp = fabs(ytemp[i] / yscal[i]);
- if(errmax < temp) errmax = temp;
- }
- errmax /= eps;
- if(errmax <= 1.0){
- *hdid = h;
- *hnext = (errmax > ERRCON ? SAFETY * h * exp(PGROW *
- log(errmax)) : 4.0 * h);
- break;
- }
- h = SAFETY * h * exp(PSHRINK * log(errmax));
- }
- for(i=0;i<n;i++) y[i] += ytemp[i] * FCOR;
- free_dvector(ytemp,0,n-1);
- free_dvector(dysav,0,n-1);
- free_dvector(ysav,0,n-1);
- }
-
-
-